<template>
  <div class="sample-tutorial">
    <button @click="handleGetMultipleData">一次性获取数据</button>
    <gc-spread-sheets class="sample-spreadsheets" @workbookInitialized="initSpread">
      <gc-worksheet>
      </gc-worksheet>
      <gc-worksheet>
      </gc-worksheet>
    </gc-spread-sheets>
    <div id="statusBar"></div>
  </div>
</template>
<script setup lang="ts">
import GC from "@grapecity-software/spread-sheets";
import {ref, toRaw} from "vue";
import '@grapecity-software/spread-sheets/styles/gc.spread.sheets.excel2013lightGray.css'
import '@grapecity-software/spread-sheets-print';
import "@grapecity-software/spread-sheets-vue";
import "@grapecity-software/spread-sheets-io";
import '@grapecity-software/spread-sheets-shapes';
import '@grapecity-software/spread-sheets-charts';
import '@grapecity-software/spread-sheets-slicers';
import '@grapecity-software/spread-sheets-pivot-addon';
import '@grapecity-software/spread-sheets-reportsheet-addon';
import "@grapecity-software/spread-sheets-tablesheet";
import "@grapecity-software/spread-sheets-ganttsheet";
import '@grapecity-software/spread-sheets-resources-zh';

// 不需要监听,会自动执行函数
// 有个问题,ASUM不直接触发的场景下,ASUM(A1,B1)-3 会显示#NAME?
class AsyncSum extends GC.Spread.CalcEngine.Functions.AsyncFunction {
  constructor() {
    super("ASUM", 1, 255);
  }

  defaultValue() {
    return "Loading...";
  }

  evaluateAsync(context: any) {
    // console.log(arguments)
    const args = arguments;
    const p = arguments[0] // row col
    // 实际参数从1 开始
    let parmList = []
    for (let i = 1; i < args.length; i++) {
      parmList.push(args[i])
    }
    const params = new URLSearchParams({
      formula: `ASUM(A1,B1)`,
    });
    // 将请求参数收集到全局数组中
    // cellRequestList.push();
    cellRequestMap.set(p.row + '-' + p.col, {
      url: `http://localhost:3000/formula?${params}`,
      body: JSON.stringify(parmList),
      context: context
    });

    // 设置默认值,默认值是文本类型,和其他的一起的时候会报#NAME?
    context.setAsyncResult("Loading...");
  }
}

class GetNumberFromServer extends GC.Spread.CalcEngine.Functions.AsyncFunction {
  constructor() {
    super("GETNUMBERFROMSERVER", 1, 2);
  }

  evaluateAsync(context: any) {
    setTimeout(() => {
      const value = Math.random() + 1;
      context.setAsyncResult(value);
    }, 500);
  }
}

class GetTimeFromServer extends GC.Spread.CalcEngine.Functions.AsyncFunction {
  constructor() {
    super("GETTIMEFROMSERVER");
  }

  evaluateAsync(context: any) {
    setTimeout(() => {
      const date = new Date();
      context.setAsyncResult(date);
    }, 500);
  }

  evaluateMode() {
    return 2;
  }

  interval() {
    return 1000;
  }
}

interface CellRequest {
  url: string;
  body: string;
  context: any;
}

GC.Spread.Common.CultureManager.culture("zh-cn");
const spreadRef = ref<GC.Spread.Sheets.Workbook>();
let CellFormulaMap = new Map<string[], string>();
// let cellRequestList: CellRequest[] = []
let cellRequestMap = new Map<string, CellRequest>(); // 数组索引是不一样的,所以会重建
const initSpread = function (spread: GC.Spread.Sheets.Workbook) {
  spreadRef.value = spread;

  GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("GETNUMBERFROMSERVER", new GetNumberFromServer());
  GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("GETTIMEFROMSERVER", new GetTimeFromServer());

  const sheet = spread.sheets[0];
  sheet.suspendPaint();
  sheet.options.allowCellOverflow = true;

  sheet.setArray(0, 0, [[5, 15, 24, 1, 3, 5, 23, 4]]);
  sheet.addCustomFunction(new AsyncSum());

  sheet.setText(1, 1, 'ASUM(A1,B1)');
  sheet.setText(2, 1, 'SUM(A1,B1)');
  sheet.setFormula(1, 2, "ASUM(A1,B1,C1)");
  sheet.getCell(1, 2).foreColor("green");
  sheet.setFormula(2, 2, "SUM(A1,B1)");

  sheet.setValue(4, 0, "Edit the formula of C2 or referenced cell' value to see how async function works.");

  sheet.setValue(8, 0, 'ChangeValue');
  sheet.setValue(8, 1, 'Formula');
  sheet.setValue(8, 2, 'Result');
  sheet.setValue(8, 3, 'Comments');
  sheet.setValue(9, 3, 'On A10 changed');
  sheet.setValue(10, 3, 'On A10 changed');
  sheet.setValue(11, 3, 'Evaluate once');
  sheet.setValue(12, 3, 'Every 2 seconds');
  sheet.setValue(9, 0, 1);
  sheet.setValue(9, 1, '=GetNumberFromServer(A10)');
  sheet.setValue(10, 1, '=Refresh(GetNumberFromServer(A10), 0)');
  sheet.setValue(11, 1, '=Refresh(GetNumberFromServer(A10), 1)');
  sheet.setValue(12, 1, '=Refresh(GetNumberFromServer(A10), 2, 2000)');

  sheet.setFormula(9, 2, '=GetNumberFromServer(A10)');
  sheet.setFormula(10, 2, '=Refresh(GetNumberFromServer(A10), 0)');
  sheet.setFormula(11, 2, '=Refresh(GetNumberFromServer(A10), 1)');
  sheet.setFormula(12, 2, '=Refresh(GetNumberFromServer(A10), 2, 2000)');
  sheet.getCell(12, 2).foreColor("green");
  sheet.setColumnWidth(0, 100);
  sheet.setColumnWidth(1, 300);
  sheet.setColumnWidth(2, 200);
  sheet.setColumnWidth(3, 200);

  sheet.setValue(15, 1, "=Refresh(now(), 2, 1000)");
  sheet.setValue(15, 3, "Every 1 second");
  sheet.setFormula(15, 2, "=Refresh(now(), 2, 1000)");
  sheet.getCell(15, 2).foreColor("green");

  sheet.setValue(18, 1, "=GetTimeFromServer()");
  sheet.setValue(18, 3, "Every 1 second");
  sheet.setFormula(18, 2, "=GetTimeFromServer()");
  sheet.getCell(18, 2).foreColor("green");
  sheet.getCell(18, 2).hAlign(GC.Spread.Sheets.HorizontalAlign.right);
  // 为什么会触发两次,网站上也是两次:propertyName一次是value一次是[styleinfo]
  sheet.bind(GC.Spread.Sheets.Events.CellChanged, (e, info: any) => {
    sheet.setValue(info.row, info.col, 'Loading');
    if (info.propertyName === "formula") {
      if (info.newValue) {
        CellFormulaMap.set([info.row, info.col], info.newValue);
      }
    }
  })
  sheet.resumePaint();
  // 底部状态栏：就绪、缩放，支持自定义
  const statusBarElement = document.getElementById('statusBar');
  if (statusBarElement) {
    let statusBar = new GC.Spread.Sheets.StatusBar.StatusBar(statusBarElement);
    statusBar.bind(spread);
  }
}

function handleGetMultipleData() {
  let reqList = Array.from(cellRequestMap.values());

  const promises = reqList.map(request => {
    return fetch(request.url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: request.body
    })
        .then(response => response.json())
        .then(data => {
          // console.log(data);
          request.context.setAsyncResult(data.result);
          return data.result;
        })
        .catch(error => {
          console.error('Error:', error);
          request.context.setAsyncResult("Error");
          return "Error";
        });

  });
  Promise.all(promises).then(results => {
    console.log("All requests completed:", results);
    // 清空请求列表
    // cellRequestList = [];
  });
}
</script>
<style scoped>
.sample-tutorial {
  width: 1400px;
  height: 880px;
}

.sample-container {
  width: calc(100% - 280px);
  height: 100%;
  float: left;
}

.sample-spreadsheets {
  width: 100%;
  height: calc(100% - 25px);
  overflow: hidden;
}

#statusBar {
  bottom: 0;
  height: 25px;
  width: 100%;
  position: relative;
}
</style>